<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>color-triangle</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
        }

        canvas {
            border: 3px solid blue;
            display: block;
        }
        #gui {
            position: absolute;
            left: 820px;
            top: 10px;
        }
    </style>
</head>
<body>
<script type="text/javascript" src="../libs/webgl-utils.js"></script>
<script type="text/javascript" src="../libs/shader.js"></script>
<script type="text/javascript" src="../libs/m3.js"></script>
<script type="text/javascript" src="../libs/dat.gui.min.js"></script>

<canvas id="color-triangle" width="800" height="600"></canvas>
<div id="gui"></div>

<script id="vertex-shader" type="x-shader/vertex-shader">
        attribute vec2 a_position;
        attribute vec4 a_color;
        uniform mat3 u_matrix;
        varying vec4 v_color;

        void main() {
            vec4 offset = vec4(0.1, 0.1, 0, 1);
            gl_Position = vec4((u_matrix * vec3(a_position, 1)).xy, 0, 1) + offset;
            v_color = a_color;
        }
    </script>

<!--mediump表示定义为中等精度, (r, g, b, a)a表示alpha透明度-->
<script id="fragment-shader" type="x-shader/fragment-shader">
        precision mediump float;
        varying vec4 v_color;
        void main() {
            gl_FragColor = v_color;
        }
    </script>
<script>
    "use strict";
    function main() {
        let canvas = document.getElementById('color-triangle');

        //判断浏览器是否支持webgl
        let gl = canvas.getContext('webgl', {antialias: true, depth: false});
        if (!gl) {
            console.log("您的浏览器不支持webgl！");
        }

        //获取GLSL的字符串
        let vertexShaderSource = document.getElementById('vertex-shader').text;
        let fragmentShaderSource = document.getElementById('fragment-shader').text;

        //创建着色器，加载着色器代码，编译着色器
        let vertexShader = createShader(gl, gl.VERTEX_SHADER, vertexShaderSource);
        let fragmentShader = createShader(gl, gl.FRAGMENT_SHADER, fragmentShaderSource);
        //链接着色器
        let program = createProgram(gl, vertexShader, fragmentShader);

        //在着色器中寻找attribute变量位置
        let positionAttributeLocation = gl.getAttribLocation(program, 'a_position');
        let colorAttributeLocation = gl.getAttribLocation(program, 'a_color');


        //在着色器中找uniform变量位置
        let matrixLocation = gl.getUniformLocation(program, 'u_matrix');

        //创建缓冲区
        let positionBuffer = gl.createBuffer();
        //将它绑定到ARRAY_BUFFER（将其视为ARRAY_BUFFER = positionBuffer）
        //绑定缓冲区
        gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
        let positions = [
            -150, -100,
            150, -100,
            -150,  100,
            150, -100,
            -150,  100,
            150,  100
        ];
        setGeometry(gl, positions);


        let colorBuffer = gl.createBuffer();
        gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
        setColor(gl, 1);

        let translation = [200, 150];
        let angleInRadians = 0;
        let scale = [1, 1];

        drawScene();

        let guiFiles = {
            "平移X": 200,
            "平移Y": 150,
            "旋转角度": 0,
            "缩放X": 1,
            "缩放Y": 1
        };

        let gui = new dat.GUI();
        gui.add(guiFiles, "平移X", 0, gl.canvas.width).onChange(function (e) {
            translation[0] = e;
            drawScene();
        });
        gui.add(guiFiles, "平移Y", 0, gl.canvas.width).onChange(function (e) {
            translation[1] = e;
            drawScene();
        });

        gui.add(guiFiles, "旋转角度", -360, 360).onChange(function(e) {
            angleInRadians = e * Math.PI / 180;
            drawScene();
        });

        gui.add(guiFiles, "缩放X", -5, 5).onChange(function(e) {
            scale[0] = e;
            drawScene();
        });

        gui.add(guiFiles, "缩放Y",-5, 5).onChange(function(e) {
            scale[1] = e;
            drawScene();
        });

        document.getElementById('gui').appendChild(gui.domElement)


        //绘制场景
        function drawScene() {

            //使画布的像素数和显示大小匹配
            webglUtils.resizeCanvasToDisplaySize(gl.canvas);
            //设置视口
            gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
            //清除canvas
            gl.clearColor(0, 0, 0, 1);
            gl.clear(gl.COLOR_BUFFER_BIT);
            //应用着色器
            gl.useProgram(program);


            //建立着色器中attribute位置变量与缓冲区之间的连接
            gl.enableVertexAttribArray(positionAttributeLocation);
            gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
            const size1 = 2;//2维坐标：每次迭代运行提取两个单位数据
            const type1 = gl.FLOAT;//每个单位的数据类型是32位浮点型
            const normalize1 = false;//不需要归一化数据
            const stride1 = 0;//每次迭代前进大小* sizeof（类型）以获得下一个位置
            const offset1 = 0;//从缓冲起始位置开始读取
            //从缓冲区取出数据
            gl.vertexAttribPointer(positionAttributeLocation, size1, type1, normalize1, stride1, offset1);


            //建立着色器中attribute颜色变量与缓冲区之间的连接
            gl.enableVertexAttribArray(colorAttributeLocation);
            gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer);
            const size2 = 4;//2维坐标：每次迭代运行提取两个单位数据
            const type2 = gl.FLOAT;//每个单位的数据类型是32位浮点型;如果为Uint8Array的8位数组，要设置为gl.UNSIGNED_BYTE
            const normalize2 = false;//不需要归一化数据
            const stride2 = 0;//每次迭代前进大小* sizeof（类型）以获得下一个位置
            const offset2 = 0;//从缓冲起始位置开始读取
            //到指定的缓冲区取出数据
            gl.vertexAttribPointer(colorAttributeLocation, size2, type2, normalize2, stride2, offset2);


            //计算矩阵
            let matrix = m3.projection(gl.canvas.clientWidth, gl.canvas.clientHeight);
            matrix = m3.translate(matrix, translation[0], translation[1]);
            matrix = m3.rotate(matrix, angleInRadians);
            matrix = m3.scale(matrix, scale[0], scale[1]);

            gl.uniformMatrix3fv(matrixLocation, false, matrix);

            let primitiveType = gl.TRIANGLES;
            let offset3 = 0;
            let count = 6;
            gl.drawArrays(primitiveType, offset3, count);//画图
        }
    }

    //通过绑定点向缓冲区绑定数据
    function setGeometry(gl, positions) {
        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(positions), gl.STATIC_DRAW);
    }

    //设置颜色
    function setColor(gl, alpha = 1) {

        gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([
            Math.random(), Math.random(), Math.random(), alpha,
            Math.random(), Math.random(), Math.random(), alpha,
            Math.random(), Math.random(), Math.random(), alpha,
            Math.random(), Math.random(), Math.random(), alpha,
            Math.random(), Math.random(), Math.random(), alpha,
            Math.random(), Math.random(), Math.random(), alpha
        ]), gl.STATIC_DRAW);
    }

    main();

</script>
</body>
</html>